home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / DATABASE / OBJ1_2.ZIP;1 / C_VIEW.PRG < prev    next >
Encoding:
Text File  |  1993-01-21  |  59.2 KB  |  1,570 lines

  1. //*****************************************************************************
  2. // C_View.prg
  3. // View class for OBJECT v2.03
  4. // Copyright (c) 1991, JHK, JHK-Software, Piestany
  5. // Please compile with: /N/M/W/A
  6. //-----------------------------------------------------------------------------
  7.  
  8. #include "InKey.ch"
  9. #include "Object.ch"
  10. #include "SetCurs.ch"
  11.  
  12. #define v_data_sep "∞"  //data separator in field->Data (database cIFR) always must be one char.
  13. #define n_foot_max 250  //length of Top and Bottom string of Report
  14.  
  15. #define v_fnc_info  "N:Abs(n)        C:AllTrim(c)    N:Asc(n)        N:At(c,c)       C:CdoW(d)       C:Chr(c)        "+;
  16.                     "C:CMonth(d)     D:CtoD(c)       D:Date()        N:Day(d)        X:Descend(e)    N:DoW(d)        "+;
  17.                     "C:DtoC(d)       C:DtoS(d)       L:Empty(e)      N:Exp(n)        C:GetEnv(c)     X:If(l,e1,e2)   "+;
  18.                     "L:IsAlpha(c)    L:IsDigit(c)    L:IsLower(c)    L:IsUpper(c)    C:Left(c,n)     N:Log(n)        "+;
  19.                     "C:Lower(c)      C:LTrim(c)      X:Max(nd,nd)    X:Min(nd,nd)    N:Month(d)      C:Pad_(e,n,c)   "+;
  20.                     "C:Right(c,n)    N:Round(n,n)    C:RTrim(c)      N:Sqrt(n)       C:Str(n,n,n)    C:StrTran(...)  "+;
  21.                     "C:SubStr(c,n,n) C:Trans(e,c)    C:Type(e)       C:Upper(c)      N:Val(c)        C:ValType(e)    "+;
  22.                     "N:Year(d)"
  23.  
  24. static VList:={}     //list of currently active view objects, add/delete: View(),Edit() / Done()
  25. static nViewID:=0    //WORK:ViewID counter, see View`Init(), used for locate in cIFR
  26. static nIndex:=0     //WORK:index into View`Report, used in programmer's defining report
  27.  
  28. create class View from DBrowse
  29.   export:
  30.   var ViewID     //0                //this is unique # for each primary View object.(thread tasks are the same ViewID), used for locate in cIFR.
  31.   var MenuID     //0                //for SlipMenu, used in View/Edit process
  32.   var MenuNtxID  //0                //for Menu`DisableItem() (thread tasks)
  33.   var MenuFltID  //0                //for Menu`DisableItem() (thread tasks)
  34.   var MenuRptID  //0                //for Menu`DisableItem() (thread tasks)
  35.   var CanGoto    //true             //enable/disable Goto command for current view
  36.   var Fields     //{}               //saved; structure: {{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid[,nMemoRowSize,nMemoColSize[,bDoGet]]},...}
  37.   var Action     //{}               //saved; structure: {{nKey,bNewProc,bPreviousProc,cShortInfo},...}
  38.   var Filter     //{{},{},{},{}}    //saved; structure: {{cName,...},{cExpr,...},{lCanModify,...},{lMarkColor,...}
  39.   var Report     //{{},{},{}}       //saved; structure: {{cName,...},{{cTop,aFields,cBottom,lOnlyTotals},...},{lCanModify,...}}  //aFields:={cShortName,cTitle,cField,cPicture,lTotal,cSubTotal}
  40.   method New=ViewNew               //o:New() --> self
  41.   method Copy=ViewCopy             //o:Copy() --> copy_of_current_view_object
  42.   method CreateObj=ViewCreateObj   //o:CreateObj() --> new object of this class
  43.   method Init=ViewInit             //o:Init()
  44.   method Select=ViewSelect         //o:Select(cAlias)
  45.   method DefWindow=ViewDefWindow   //o:DefWindow(Name,R,C,Rs,Cs,Clr)
  46.   method AddBlock=ViewAddBlock     //o:AddBlock(cLongName,cShortName,cVarName,bBlock,bDoGet,cPicture,bWhen,bValid)
  47.   method AddMemo=ViewAddMemo       //o:AddMemo(cLongName,cShortName,cField,bWhen,bValid,nRowSize,nColSize)
  48.   method AddField=ViewAddField     //o:AddField(cLongName,cShortName,cField,cPicture,bWhen,bValid)
  49.   method AddFilter=ViewAddFilter   //o:AddFilter(cName,cExpr,lMark)
  50.   method AddRAll=ViewAddRAll       //o:AddRAll(cName,cTop,aFields,cBottom,lOnlyTotals)    //add all report: cName=menu_name,{"top_line1;line2",{{ShortName,cField,lTotal,cSubTotal},{ShortName...},...},"bottom_line1;line2",false}
  51.   method AddReport=ViewAddReport   //o:AddReport(cName,lOnlyTotals)                       //one:   "menu_name"
  52.   method AddRTop=ViewAddRTop       //o:AddRTop(cTop)                                      //one:   "top_line_1;top_line2..."
  53.   method AddRField=ViewAddRField   //o:AddRField(cTitle,aField,cPicture,lTotal,cSubTotal) //repeat:"ShortName,cField,lTotal,cSubTotal;ShortName..."
  54.   method AddRBottom=ViewAddRBottom //o:AddRBottom(cBottom)                                //one:   "bottom_line1;line2..."}
  55.   method AddAction=ViewAddAction   //o:AddAction(nKey,bProcedure,cInfo)
  56.   method View=ViewView             //o:View(ID,Name,R,C,Rs,Cs,Clr,Shadow)  //ID is menu id number (this is ptr into Menu`Avail array)
  57.   method Edit=ViewEdit             //o:Edit(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  58.   method ViewEdit=ViewViewEdit     //o:ViewEdit(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  59.   method Goto=ViewGoto             //o:Goto(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  60.   method Locate=ViewLocate         //o:Locate(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  61.   method PreGoto=ViewPreGoto       //o:PreGoto(Menu,MdId)
  62.   method PostGoto=ViewPostGoto     //o:PostGoto(Menu,MdId)
  63.   method SetIndex=ViewSetIndex     //o:SetIndex(ID,R,C,CurSize,Clr,Shadow)
  64.   method SetFilter=ViewSetFilter   //o:SetFilter(ID,R,C,CurSize,Clr,Shadow)
  65.   method SetReport=ViewSetReport   //o:SetReport(ID,WinName,R,C,CurSize,Clr,Shadow)
  66.   method ModIndex=ViewModIndex     //o:ModIndex(ID,WinName,R,C,CurSize,Clr,Shadow)
  67.   method ModFilter=ViewModFilter   //o:ModFilter(ID,WinName,R,C,CurSize,Clr,Shadow)
  68.   method ModReport=ViewModReport   //o:ModReport(ID,WinName,R,C,CurSize,Clr,Shadow)
  69.   method VProcess=ViewVProcess     //o:VProcess()
  70.   method Done=ViewDone             //o:Done(lRePaint)
  71.   method EndViewEdit=ViewEndViewEdit //o:EndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow)
  72.   endclass
  73.  
  74.  
  75. //*****************************************************************************
  76. // View:New() --> self
  77. // default values for this object
  78. //
  79. constructor ViewNew()
  80.   ::ViewID:=0
  81.   ::MenuID:=0
  82.   ::MenuNtxID:=0
  83.   ::MenuFltID:=0
  84.   ::MenuRptID:=0
  85.   ::CanGoto:=true
  86.   ::Fields:={}
  87.   ::Action:={}
  88.   ::Filter:={{},{},{},{}}
  89.   ::Report:={{},{},{}}
  90.   return(self)
  91.  
  92.  
  93. //*****************************************************************************
  94. // View:CreateObj() --> self
  95. // default values for this object
  96. //
  97. method function ViewCreateObj()
  98.   return(object of View)
  99.  
  100.  
  101. //-----------------------------------------------------------------------------
  102. // GetVList() --> VList
  103. // return view list
  104. //
  105. function GetVList()
  106.   return(VList)
  107.  
  108.  
  109. //*****************************************************************************
  110. // View:Init() --> true
  111. // dummy initialize new view object
  112. // this is not true init! You must call View:View() or View:Edit()! (need for Task:Init())
  113. // this is need for postInitialization with user defined fnc in main program (see OExample.prg)
  114. //
  115. method function ViewInit()
  116.   if Select(cBasic)==0    //for building view(s) the databases must be opened!
  117.     GetLastDbf():Open()   //Open /Create the databases
  118.   endif
  119.   ::ViewID:=++nViewID
  120.   AAdd(::Filter[1]," "+ResTxt(046)+" ")
  121.   AAdd(::Filter[2],"")
  122.   AAdd(::Filter[3],false)
  123.   AAdd(::Filter[4],false)
  124.   return(true)
  125.  
  126.  
  127. //*****************************************************************************
  128. // View:Select(cAlias) --> true
  129. // save cAlias, for later selecting master database area, for this view.
  130. //
  131. method function ViewSelect(cAlias)
  132.   local OldS:=Select()
  133.   cAlias:=Upper(cAlias)
  134.   ::Alias:=cAlias
  135.   ::OneDbf:=GetOneDbf(cAlias)        //primary index definitions
  136.   select (cIFR)
  137.   set filter to field->ViewID==::ViewID and field->Code=="I"  //indexes
  138.   DbEval({||InDbRead(self)})
  139.   ::OneDbf:NtxOpen(false)
  140.   select (cIFR)  //restore work area
  141.   set filter to field->ViewID==::ViewID and field->Code=="F"  //filters
  142.   DbEval({||FiDbRead(self)})
  143.   set filter to field->ViewID==::ViewID and field->Code=="R"  //reports
  144.   DbEval({||ReDbRead(self)})
  145.   set filter to
  146.   select (OldS)
  147.   return(true)
  148.  
  149. static function InDbRead(View)
  150.   local d:=ListAsArray(RTrim(field->Data),v_data_sep)
  151.   View:OneDbf:AddNtx(d[1],d[2],d[3],d[4]=="T",d[5]=="T")   //cName,cFile,cKey,lUnique,lUser
  152.   return(true)
  153.  
  154. static function FiDbRead(View)
  155.   local d:=ListAsArray(RTrim(field->Data),v_data_sep)
  156.   AAdd(View:Filter[1],d[1])        //cName
  157.   AAdd(View:Filter[2],d[2])        //cExpression
  158.   AAdd(View:Filter[3],true)        //lCanModify
  159.   AAdd(View:Filter[4],d[3]=="T")   //lMark
  160.   return(true)
  161.  
  162. static function ReDbRead(View)
  163.   local dt:=ListAsArray(RTrim(field->Data),v_data_sep)   //field->Data="cName∞cTopLine1;cTopLine2∞cShortName,cTitle,cField,cPicture,lTotal,cSubTotal;cShortName...∞cBottom1;cBottom2∞lOnlyTotals"
  164.   local fs:=ListAsArray(dt[3],";")                       //fs:={"cShortName,cTitle,cField...",...}
  165.   local a:={}                                            //empty a=aFields
  166.   AEval(fs,{|e|AAdd(a,ListAsArray(e))})                  //load a=aFields
  167.   AEval(a,{|e,i|if(Empty(e[4]),a[i,4]:=nil,),;
  168.                 e[5]:=(e[5]=="T"),;
  169.                 if(Empty(e[6]),a[i,6]:=nil,);
  170.           };
  171.        )
  172.   AAdd(View:Report[1],dt[1])                        //cName
  173.   AAdd(View:Report[2],{dt[2],a,dt[4],dt[5]=="T"})   //cTop,aFields,cBottom,lOnlyTotals
  174.   AAdd(View:Report[3],true)                         //lCanModify
  175.   return(true)
  176.  
  177.  
  178. //*****************************************************************************
  179. // View:DefWindow(Name,R,C,Rs,Cs,Clr,Shadow)
  180. // update the window data for this object
  181. //
  182. method function ViewDefWindow(Name,R,C,Rs,Cs,Clr,Shadow)
  183.   default Rs := MaxRow()-7
  184.   default Cs := MaxCol()-9
  185.   default R  := (MaxRow()-Rs)/2
  186.   default C  := (MaxCol()-Cs)/2
  187.   ::Form:Row := R
  188.   ::Form:Col := C
  189.   store value Name   into ::Name
  190.   store value Rs     into ::Form:RowSize
  191.   store value Cs     into ::Form:ColSize
  192.   store value Clr    into ::Color
  193.   store value Shadow into ::Shadow
  194.   ::Form:MaxRows := ::Form:RowSize   //Mask window cannot be "sizeable"
  195.   ::Form:MaxCols := ::Form:ColSize
  196.   ::Form:MinRows := ::Form:RowSize
  197.   ::Form:MinCols := ::Form:ColSize
  198.   return(true)
  199.  
  200.  
  201. //*****************************************************************************
  202. // View:AddBlock(cLongName,cShortName,cVarName,bBlock,bDoGet,cPicture,bWhen,bValid) --> true
  203. // save (add) block (mem_var, unstandart_field) for later rendering in this view.
  204. //
  205. method function ViewAddBlock(LongN,ShortN,VarN,Block,DoGet,Picture,When,Valid)
  206.   default LongN to ShortN
  207.   default VarN to ShortN
  208.   VarN:=Upper(VarN)
  209.   if( At("->",VarN)==0, VarN:="MEMORY->"+VarN, )
  210.   AAdd(::Fields,{LongN,ShortN,VarN,Block,Picture,When,Valid,,,DoGet})  //len=10
  211.   HelpAssoc(VarN,ShortN,HelpReserved(,+1))   //code block can be unique for every View object
  212.   return(true)
  213.  
  214.  
  215. //*****************************************************************************
  216. // View:AddMemo(cLongName,cShortName,cField,bWhen,bValid,nRowSize,nColSize) --> true
  217. // save (add) memo field for later rendering in this view.
  218. //
  219. method function ViewAddMemo(cLongN,cShortN,cField,bWhen,bValid,nRowSize,nColSize)
  220.   local f,s,dbf,i
  221.   cField:=Upper(cField)
  222.   f:=GetField(cField)
  223.   s:=GetSelect(cField); if Empty(s) or s=="FIELD"; s:=::Alias; endif
  224.   dbf:=GetOneDbf(s)
  225.   i:=AScan(dbf:Struc,{|e|e[1]==f})
  226.   default cShortN  to cField
  227.   default cLongN   to cShortN
  228.   default nRowSize to Int(MaxRow()/3)
  229.   default nColSize to Int(MaxCol()/2)
  230.   default bWhen    to dbf:PreBlock[i]
  231.   default bValid   to dbf:PostBlock[i]
  232.   AAdd(::Fields,{cLongN,cShortN,s,f,,bWhen,bValid,nRowSize,nColSize}) //len=9
  233.   if !ChangeAssoc(s+"->"+f,cShortN,)
  234.     Abort("Association cannot be changed.")
  235.   endif
  236.   return(true)
  237.  
  238.  
  239. //*****************************************************************************
  240. // View:AddField(cLongName,cShortName,cField,cPicture,bWhen,bValid) --> true
  241. // save (add) view field for later rendering in this view.
  242. //
  243. method function ViewAddField(cLongN,cShortN,cField,cPicture,bWhen,bValid)
  244.   local f,s,dbf,i
  245.   cField:=Upper(cField)
  246.   f:=GetField(cField)
  247.   s:=GetSelect(cField); if Empty(s) or s=="FIELD"; s:=::Alias; endif
  248.   dbf:=GetOneDbf(s)
  249.   i:=AScan(dbf:Struc,{|e|e[1]==f})
  250.   default cShortN  to cField
  251.   default cLongN   to cShortN
  252.   default cPicture to dbf:Pict[i]
  253.   default bWhen    to dbf:PreBlock[i]
  254.   default bValid   to dbf:PostBlock[i]
  255.   AAdd(::Fields,{cLongN,cShortN,s,f,cPicture,bWhen,bValid}) //len=7
  256.   if !ChangeAssoc(s+"->"+f,cShortN,)
  257.     Abort("Association cannot be changed.")
  258.   endif
  259.   return(true)
  260.  
  261.  
  262. //*****************************************************************************
  263. // View:AddAction(nKey,bProcedure,cInfo) --> true
  264. // add new hot-key action into this view.
  265. //
  266. method function ViewAddAction(nKey,bProcedure,cInfo)
  267.   default cInfo to ""
  268.   AAdd(::Action,{nKey,bProcedure,nil,cInfo})  //cInfo is short text that will be added into dialogue line
  269.   return(true)
  270.  
  271.  
  272. //*****************************************************************************
  273. // View:AddFilter(cName,cExpr,lMark) --> true
  274. // add new filter expression into this view.
  275. //
  276. method function ViewAddFilter(cName,cExpr,lMark)
  277.   local nIndex:=AScan(::Filter[3],true)
  278.   default lMark:=false
  279.   ATrueIns(::Filter[1],nIndex," "+AllTrim(cName)+" ")   //Name
  280.   ATrueIns(::Filter[2],nIndex,cExpr)                    //Expression
  281.   ATrueIns(::Filter[3],nIndex,false)                    //CanModify
  282.   ATrueIns(::Filter[4],nIndex,lMark)                    //Colored/Hidden
  283.   return(true)
  284.  
  285.  
  286. //*****************************************************************************
  287. // View:AddRAll(cName,cTop,aFields,cBottom,lOnlyTotals) --> true
  288. // add (save) new ALL report into this view.
  289. //
  290. method function ViewAddRAll(cName,cTop,aFields,cBottom,lOnlyTotals)
  291.   nIndex:=AScan(::Report[3],true)
  292.   default cTop to ""
  293.   default cBottom to ""
  294.   default lOnlyTotals to false
  295.   ATrueIns(::Report[1],nIndex," "+AllTrim(cName)+" ")              //Name
  296.   ATrueIns(::Report[2],nIndex,{cTop,aFields,cBottom,lOnlyTotals})  //Expression
  297.   ATrueIns(::Report[3],nIndex,false)                               //CanModify
  298.   return(true)
  299.  
  300.  
  301. //*****************************************************************************
  302. // View:AddReport(cName,lOnlyTotals) --> true
  303. // create new report arrays for this view
  304. //
  305. method function ViewAddReport(cName,lOnlyTotals)
  306.   default lOnlyTotals:=false
  307.   nIndex:=AScan(::Report[3],true)                      //Save index for currently builded report
  308.   ATrueIns(::Report[1],nIndex," "+AllTrim(cName)+" ")  //Name
  309.   ATrueIns(::Report[2],nIndex,{"",{},"",lOnlyTotals})  //Empty Expression={cTop,aFields,cBottom,lOnlyTotals}
  310.   ATrueIns(::Report[3],nIndex,false)                   //CanModify
  311.   fill empty nIndex with Len(::Report[3])              //set end_of_array
  312.   return(true)
  313.  
  314.  
  315. //*****************************************************************************
  316. // View:AddRTop(cTop) --> true
  317. // add all top lines into this array
  318. //
  319. method function ViewAddRTop(cTop)
  320.   ::Report[2,nIndex,1]:=cTop
  321.   return(true)
  322.  
  323.  
  324. //*****************************************************************************
  325. // View:AddRField(cTitle,cField,cPicture,lTotal,cSubTotal) --> true
  326. // add (save) new field report into this view.
  327. //
  328. method function ViewAddRField(cTitle,cField,cPicture,lTotal,cSubTotal)
  329.   local i
  330.   cField:=Upper(cField)                                 //work around field
  331.   if At("->",cField)==0 or SubStr(cField,5)=="FIELD"
  332.     cField:=::Alias+"->"+SubStr(cField,At("->",cField))
  333.   endif
  334.   if !Empty(cSubTotal)
  335.     cSubTotal:=Upper(cSubTotal)                         //work around subtotal
  336.     if At("->",cSubTotal)==0 or SubStr(cSubTotal,5)=="FIELD"
  337.       cSubTotal:=::Alias+"->"+SubStr(cSubTotal,At("->",cSubTotal))
  338.     endif
  339.   endif
  340.   if cTitle==nil or cPicture==nil
  341.     if (i:=AScan(::Fields,{|e|e[3]+"->"+e[4]==cField}))>0  //find cField in View
  342.       default cTitle   to ::Fields[i,2]
  343.       default cPicture to ::Fields[i,5]
  344.     endif
  345.   endif
  346.   AAdd(::Report[2,nIndex,2],{"",cTitle,cField,cPicture,lTotal,cSubTotal})
  347.   return(true)
  348.  
  349.  
  350. //*****************************************************************************
  351. // View:AddRBottom(cBottom) --> true
  352. // add bottom lines into this array
  353. //
  354. method function ViewAddRBottom(cBottom)
  355.   ::Report[2,nIndex,3]:=cBottom
  356.   return(true)
  357.  
  358.  
  359. //*****************************************************************************
  360. // View:View(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> true
  361. // virtual view process, last initialization
  362. //
  363. method function ViewView(nID,Name,R,C,Rs,Cs,Clr,Shadow)
  364.   local V:=::Copy()  //now we must to create copy of view object
  365.   //default values
  366.   V:CanEdit:=false
  367.   V:CanAppend:=false
  368.   V:Color:=m->Color:View
  369.   V:EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow)
  370.   return(V:Process())
  371.  
  372.  
  373. //*****************************************************************************
  374. // View:Edit(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil
  375. // virtual edit process, last initialization
  376. //
  377. method function ViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow)
  378.   local V:=::Copy()  //now we must to create copy of view object
  379.   V:EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow)
  380.   return(V:Process())
  381.  
  382.  
  383. //*****************************************************************************
  384. // View:ViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil
  385. // virtual view_or_edit process, no AClone() of this object
  386. //
  387. method function ViewViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow)
  388.   ::EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow)
  389.   return(::Process())
  390.  
  391.  
  392. //*****************************************************************************
  393. // V:=View:Copy()
  394. // creating copy of view object
  395. //
  396. method function ViewCopy()
  397.   local V:=::CreateObj()
  398.                                //_________________Loc_________________
  399.   V:Row:=::Row                 // 3
  400.   V:Col:=::Col                 // 4
  401.                                //_________________Box_________________
  402.   V:Name:=::Name               // ""
  403.   V:RowSize:=::RowSize         // MaxRow()-7
  404.   V:ColSize:=::ColSize         // MaxCol()-9
  405.   V:Color:=::Color             // m->Color`Edit
  406.   V:Shadow:=::Shadow           // true
  407.                                //_________________Window______________
  408.   V:ID:=::ID                   // 0
  409.   V:WRow:=::WRow               // 3
  410.   V:WCol:=::WCol               // 4
  411.   V:WRowSize:=::WRowSize       // MaxRow()-7
  412.   V:WColSize:=::WColSize       // MaxCol()-9
  413.   V:IsMax:=::IsMax             // false
  414.   V:IsMin:=::IsMin             // false
  415.   V:MaxRows:=::MaxRows         // MaxRow()-3
  416.   V:MaxCols:=::MaxCols         // MaxCol()-1
  417.   V:MinRows:=::MinRows         // 1
  418.   V:MinCols:=::MinCols         // 5
  419.   V:UpFlag:=::UpFlag           // false
  420.   V:Screen:=::Screen           // ""
  421.   V:UpScreen:=::UpScreen       // ""
  422.   V:BkScreen:=::BkScreen       // ""
  423.   V:RCInfo:=::RCInfo           // ""
  424.   V:InfoMsg:=::InfoMsg         // ""
  425.   //V:Frame:=::Frame           // (object of Frame) ƒ> € can not be copyied €
  426.                                //_________________Task________________
  427.   V:IsDead:=::IsDead           // false
  428.   V:DoneBlock:=::DoneBlock     // {||true}
  429.                                //_________________Browse______________
  430.   V:CanShowSkip:=::CanShowSkip // false
  431.   V:CanEdit:=::CanEdit         // true
  432.   V:CanAppend:=::CanAppend     // true
  433.   V:CanSwap:=::CanSwap         // true
  434.   V:CanSkip:=::CanSkip         // true
  435.   V:FormActive:=::FormActive   // false
  436.   V:Direction:=::Direction     // K_RIGHT
  437.   V:QuickEdit:=::QuickEdit     // true
  438.   V:SetConfirm:=::SetConfirm   // Set(_SET_CONFIRM)
  439.   V:AddMsg:=::AddMsg           // ""
  440.   V:InsBlock:=::InsBlock       // {|o|nil}
  441.   V:DelBlock:=::DelBlock       // {|o|nil}
  442.   V:InfoBlock:=::InfoBlock     // {|o|nil}
  443.   V:GetList:=AClone(::GetList)     // {}
  444.   V:DoGetList:=AClone(::DoGetList) //{}
  445.   V:DelGet:=AClone(::DelGet)       // {}
  446.   V:DelDoGet:=AClone(::DelDoGet)   // {}
  447.   V:Tb:=::Tb                   // nil
  448.   V:PreSkip:=::PreSkip
  449.   V:PostSkip:=::PostSkip
  450.   V:Freeze:=::Freeze           // 0
  451.   V:FormTop:=::FormTop         // 1
  452.   V:Form:=(object of Window)   // (object of Window) ƒƒ> see Browse:PostInit()
  453.   V:Form:Row:=::Form:Row
  454.   V:Form:Col:=::Form:Col
  455.   V:Form:RowSize:=::Form:RowSize
  456.   V:Form:ColSize:=::Form:ColSize
  457.   V:Form:MaxRows:=::Form:MaxRows
  458.   V:Form:MaxCols:=::Form:MaxCols
  459.   V:Form:MinRows:=::Form:MinRows
  460.   V:Form:MinCols:=::Form:MinCols
  461.  
  462.   V:SetUp:=::SetUp             // false
  463.                                //_________________DBrowse_____________
  464.   V:Alias:=::Alias             // ""
  465.   V:RecNo:=::RecNo             // 1
  466.   V:IndexNo:=::IndexNo         // 0
  467.   V:FilterNo:=::FilterNo       // 0
  468.   V:FilterExp:=::FilterExp     // ""
  469.   V:FilterBExp:=::FilterBExp   // {||...}
  470.   V:FilterMark:=::FilterMark   // false
  471.   V:InsBlock:=::InsBlock       // {|o|o``DoInsert()}
  472.   V:DelBlock:=::DelBlock       // {|o|o``DoDelete()}
  473.   V:InfoBlock:=::InfoBlock     // {|o|o``DoInfo()}
  474.                                //_________________View________________
  475.   V:ViewID:=::ViewID           // 0
  476.   V:MenuID:=::MenuID           // 0
  477.   V:MenuNtxID:=::MenuNtxID     // 0
  478.   V:MenuFltID:=::MenuFltID     // 0
  479.   V:MenuRptID:=::MenuRptID     // 0
  480.   V:CanGoto:=::CanGoto         // true
  481.   V:Fields:=AClone(::Fields)   // {}
  482.   V:Action:=AClone(::Action)   // {}
  483.   // V:Filter:=::Filter        // {{},{},{},{}}    ƒø  must be the same
  484.   // V:Report:=::Report        // {{},{},{}}        √> as parent,
  485.   // V:OneDbf:=::OneDbf        // object of OneDbf ƒŸ  see EndViewInit()
  486.   return(V)
  487.  
  488.  
  489. //*****************************************************************************
  490. // V:EndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil
  491. // post initialization before dbrowse_process
  492. //
  493. method function ViewEndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow)
  494.   local Ch
  495.   store value nID into ::MenuID
  496.   ::Filter:=View:Filter  //array pointer  ⁄ƒƒƒø  all threaded object
  497.   ::Report:=View:Report  //array pointer  ≥ ! ≥  MUST HAVE THE SAME
  498.   ::OneDbf:=View:OneDbf  //object pointer ¿ƒƒƒŸ  index, filter and report
  499.   Ch:=::FilterNo+1              //get new filter index
  500.   ::FilterExp:=::Filter[2,Ch]   //save new filter expression !!!
  501.   ::FilterBExp:=if(Empty(::Filter[2,Ch]),{||false},&("{||"+::Filter[2,Ch]+"}"))  //...as code block
  502.   ::FilterMark:=::Filter[4,Ch]  //flag to_Mark (true) / to_Hide (false)
  503.   ::super(DBrowse):Init(Name,R,C,Rs,Cs,Clr,Shadow)
  504.   AEval(::Fields,{|e|Build(self,e)})
  505.   AAdd(VList,self)  //save view into view_list
  506.   return(true)
  507.  
  508.  
  509. //-----------------------------------------------------------------------------
  510. // V::Build(V,e) --> true
  511. // build one editable item for DBrowse
  512. // e={cLongName,cShortName,cAlias/cVarName,cField/bBlock,cPicture,bWhen,bValid,nRowSize,nColSize,bDoGet}
  513. //    -1------- -2-------- -3------------- -4----------- -5------ -6--- -7---- -8------ -9------ -10---
  514. //
  515. static function Build(V,e)
  516.   local ln:=Len(e)
  517.   do case
  518.     case ln=10; BuildBlock(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[10])    //LongName,ShortName,VarName,Block,Picture,When,Valid,DoGet
  519.     case ln=9;  BuildMemo(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9]) //LongName,ShortName,Alias,  Field,Picture,When,Valid,RowSize,ColSize
  520.     case ln=7;  BuildField(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7])          //LongName,ShortName,Alias,  Field,Picture,When,Valid
  521.   endcase
  522.   return(true)
  523.  
  524.  
  525. //-----------------------------------------------------------------------------
  526. // V::BuildBlock(LongN,ShortN,VarName,Block,Picture,When,Valid,DoGet) --> true
  527. // build one editable item for DBrowse
  528. //
  529. static function BuildBlock(V,LongN,ShortN,VarName,Block,Picture,When,Valid,DoGet)
  530.   local g
  531.   SetColor(V:Color)
  532.   g:=GetNew(0,0,Block,VarName)
  533.   g:Picture:=Picture
  534.   g:PreBlock:=When
  535.   g:PostBlock:=Valid
  536.   g:Cargo:=Array(nLenCargo)
  537.   g:Cargo[nLongName]:=LongN
  538.   g:Cargo[nShortName]:=ShortN
  539.   g:Cargo[nAlias]:=V:Alias
  540.   V:AddGet(g,DoGet)
  541.   return(true)
  542.  
  543.  
  544. //-----------------------------------------------------------------------------
  545. // V::BuildMemo(LongN,ShortN,Alias,Field,Picture,When,Valid,RowSize,ColSize) --> true
  546. // build memo_get for DBrowse
  547. //
  548. static function BuildMemo(V,LongN,ShortN,Alias,Field,Picture,When,Valid,RowSize,ColSize)
  549.   local g
  550.   default When to {||true}
  551.   default Valid to {||true}
  552.   SetColor(V:Color)
  553.   g:=GetNew(0,0,{||ResTxt(134)},Alias+"->"+Field)
  554.   g:Picture:=Picture
  555.   g:Cargo:=Array(nLenCargo)
  556.   g:Cargo[nLongName]:=LongN
  557.   g:Cargo[nShortName]:=ShortN
  558.   g:Cargo[nAlias]:=Alias
  559.   g:PostBlock:={|g,lEdit|MemoPostBlock(V,g,lEdit,FieldWBlock(Field,Select(Alias)),When,Valid,RowSize,ColSize)}
  560.   V:AddGet(g)
  561.   return(true)
  562.  
  563.  
  564. static function MemoPostBlock(V,g,lEdit,Block,When,Valid,RowSize,ColSize)
  565.   local x
  566.   local l:=LastKey()
  567.   if l==10 or l==13 or V:QuickEdit and 32<=l and l<=126
  568.     if Eval(When,g,lEdit) and ((!lEdit)or((g:Cargo[nAlias])->(NetRLock(true))))
  569.       SaveDOut(V:AddMsg)
  570.       if lEdit; x:=Eval(Block); endif
  571.       ReadHelpVar(g:Name)
  572.       Memo(Block,lEdit,,,,RowSize,ColSize)
  573.       ReadHelpVar("")
  574.       RestDOut()
  575.       g:SetFocus()
  576.         if lEdit and (x<>Eval(Block))
  577.           g:OverStrike(Left(ResTxt(134),1))  //set non-assignable g:changed onto true
  578.         endif
  579.         Eval(Valid,g,lEdit)
  580.       g:KillFocus()
  581.       if lEdit; (g:Cargo[nAlias])->(DbUnLock()); endif
  582.     else
  583.       if 32<=l and l<=126; InKeyWait(); endif  //remove key from queue
  584.     endif
  585.     return(false)
  586.   endif
  587.   return(true)
  588.  
  589.  
  590. //-----------------------------------------------------------------------------
  591. // V::BuildField(LongN,ShortN,Alias,Field,Picture,When,Valid) --> true
  592. // build field_get for DBrowse
  593. //
  594. static function BuildField(V,LongN,ShortN,Alias,Field,Picture,When,Valid)
  595.   local g
  596.   SetColor(V:Color)
  597.   g:=GetNew(0,0,FieldWBlock(Field,Select(Alias)),Alias+"->"+Field)
  598.   g:Picture:=Picture
  599.   g:PreBlock:=When
  600.   g:PostBlock:=Valid
  601.   g:Cargo:=Array(nLenCargo)
  602.   g:Cargo[nLongName]:=LongN
  603.   g:Cargo[nShortName]:=ShortN
  604.   g:Cargo[nAlias]:=Alias
  605.   V:AddGet(g)
  606.   return(true)
  607.  
  608.  
  609. //*****************************************************************************
  610. // View:Goto(ID,Name,R,C,Rs,Cs,Clr,Shadow) --> true
  611. // go to record
  612. //
  613. method function ViewGoto(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  614.   local n
  615.   local Lt:=GetLastView(self)
  616.   local object Box of Box
  617.   if Empty(Lt); Lt:=self; endif
  618.   default Name to ""
  619.   default R to Lt:Row
  620.   default C to Lt:Col+2
  621.   default Rs to 1
  622.   default Cs to Len(ResTxt(050))+10
  623.   default Clr to Lt:Color
  624.   object Box of Box
  625.   Box:GoodInit(Name,R,C,Rs,Cs,-1,Clr,Shadow)
  626.   n:=EditIt(RecNo(),ResTxt(050),,Box:Row,Box:Col,Clr)
  627.   if n<RecNo(); Lt:Tb:RowPos:=1; endif
  628.   do case
  629.     case n<1;         go top
  630.     case n>LastRec(); go bottom
  631.     otherwise;        go n
  632.   endcase
  633.   SetLastKey(0)
  634.   Lt:RecNo:=RecNo()
  635.   Lt:VPaint()
  636.   return(true)
  637.  
  638.  
  639. //*****************************************************************************
  640. // View:Locate(ID,Name,R,C,Rs,Cs,Clr,Shadow) --> true
  641. // locate for record
  642. //
  643. method function ViewLocate(ID,Name,R,C,Rs,Cs,Clr,Shadow)
  644.   local n,cc,g,IsMemo:=false
  645.   local Lt:=GetLastView(self)
  646.   local object Box of Box
  647.   if Empty(Lt); Lt:=self; endif
  648.   g:=Lt:GetList[Lt:Tb:ColPos]
  649.   cc:=Transform(Eval(g:block),g:Picture)
  650.   if cc==ResTxt(134); IsMemo:=true; cc:=Space(40); endif
  651.   default Name to ""
  652.   default R to Lt:Row
  653.   default C to Lt:Col+2
  654.   default Rs to 1
  655.   default Cs to Len(cc)+Len(ResTxt(177))+Len(g:Cargo[nShortName])+4
  656.   default Clr to Lt:Color
  657.   object Box of Box
  658.   Box:GoodInit(Name,R,C,Rs,Cs,-1,Clr,Shadow)
  659.   cc:=AllTrim(EditIt(cc,ResTxt(177)+" "+g:Cargo[nShortName],,Box:Row,Box:Col,Clr))
  660.   n:=RecNo()
  661.   if !Empty(cc) and LastKey()<>K_ESC
  662.     SaveDOut(ResTxt(176))
  663.     DbSkip()
  664.     if IsMemo
  665.       cc:="{||!('"+cc+"' $ "+g:Name+")}"
  666.       DbEval({||nil},,&(cc))
  667.     else
  668.       DbEval({||nil},,{||!(cc $ Transform(Eval(g:block),g:picture))})
  669.     endif
  670.     if !Eof()
  671.       refresh table
  672.     else
  673.       go n
  674.       Alert(ResTxt(178))
  675.     endif
  676.     RestDOut()
  677.   endif
  678.   SetLastKey(0)
  679.   Lt:RecNo:=RecNo()
  680.   Lt:VPaint()
  681.   return(true)
  682.  
  683.  
  684. //*****************************************************************************
  685. // View:PreGoto(Menu,MdId) --> true
  686. // prevalidation for View:Goto()
  687. //
  688. method function ViewPreGoto(Menu,MdId)
  689.   if Empty(GetLastView(self))
  690.     Menu:DisableItem(((Menu:GetMD(MdId)):Data[3]):ID, false)
  691.     Menu:DisableItem(((Menu:GetMD(MdId)):Data[4]):ID, false)
  692.   else
  693.     Menu:EnableItem(((Menu:GetMD(MdId)):Data[3]):ID, false)
  694.     Menu:EnableItem(((Menu:GetMD(MdId)):Data[4]):ID, false)
  695.   endif
  696.   return(true)
  697.  
  698.  
  699. //*****************************************************************************
  700. // View:PostGoto(Menu,MdId) --> true
  701. // postvalidation for View:Goto()
  702. //
  703. method function ViewPostGoto(Menu,MdId)
  704.   Menu:EnableItem(((Menu:GetMD(MdId)):Data[3]):ID, false)
  705.   Menu:EnableItem(((Menu:GetMD(MdId)):Data[4]):ID, false)
  706.   return(true)
  707.  
  708.  
  709. //*****************************************************************************
  710. // View:SetIndex(nID,R,C,CurSize,Clr,Shadow) --> true
  711. // select index and set it
  712. //
  713. method function ViewSetIndex(ID,R,C,CurSize,Clr,Shadow)
  714.   local Ch,LastView,i
  715.   local arl:={}
  716.   local ar:={" "+ResTxt(045)+" "}
  717.   local object Mnu of Mnu
  718.   AEval(::OneDbf:Ntx,{|e|AAdd(ar," "+e[1])})   //cName
  719.   GetArl(self,ar,@arl,@LastView)               //build arl & get LastView
  720.   i:=1
  721.   AEval(::OneDbf:Ntx,{|e|i++,if(Empty(e[3]),arl[i]:=false,nil)})
  722.   Mnu:Init("",R,C,CurSize,ar,arl,Clr,Shadow)
  723.   Ch:=Mnu:Process()
  724.   Mnu:Done()
  725.   if Ch>0
  726.     set order to (Ch-1)
  727.     LastView:IndexNo:=(Ch-1)   //save index order into curent view (last active task)
  728.     LastView:Tb:RowPos:=1
  729.     LastView:Tb:Configure()
  730.   endif
  731.   if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif
  732.   return(true)
  733.  
  734.  
  735. //-----------------------------------------------------------------------------
  736. // View::GetArl(ar,@arl,@LastView) --> true
  737. // build paralel array of logical values that specify the selectable menu items
  738. // and look for last running view object
  739. //
  740. static function GetArl(View,ar,arl,LastView)
  741.   arl:=Array(Len(ar))  //arl=array for enable/disable items in ar
  742.   LastView:=GetLastView(View)
  743.   AFill(arl,LastView<>nil)
  744.   return(true)
  745.  
  746.  
  747. //-----------------------------------------------------------------------------
  748. // View::GetLastView() --> LastView/nil
  749. // look for last running view object
  750. //
  751. static function GetLastView(View)
  752.   local Lt:=SetLastTask()
  753.   if !Empty(Lt) and Lt:ClassName==View:ClassName and Lt:ViewID==View:ViewID
  754.     return(Lt)
  755.   endif
  756.   return(nil)
  757.  
  758.  
  759. //*****************************************************************************
  760. // View:SetFilter(nID,R,C,CurSize,Clr,Shadow) --> true
  761. // select filter from mnu and set it
  762. //
  763. method function ViewSetFilter(nID,R,C,CurSize,Clr,Shadow)
  764.   local Ch,LastView,arl
  765.   local ar:=::Filter[1]
  766.   local object Mnu of Mnu
  767.   GetArl(self,ar,@arl,@LastView)  //build arl & get LastView
  768.   Mnu:Init("",R,C,CurSize,ar,arl,Clr,Shadow)
  769.   Ch:=Mnu:Process()
  770.   Mnu:Done()
  771.   if Ch>0 and ( !(LastView:FilterExp==::Filter[2,Ch]) or ;
  772.                 !(LastView:FilterMark==::Filter[4,Ch]) )
  773.     LastView:FilterNo:=Ch-1              //save new filter index
  774.     LastView:FilterExp:=::Filter[2,Ch]   //save new filter expression
  775.     LastView:FilterBExp:=if(Empty(::Filter[2,Ch]),{||false},&("{||"+::Filter[2,Ch]+"}"))  //...as code block
  776.     LastView:FilterMark:=::Filter[4,Ch]  //flag to_Mark (true) / to_Hide (false)
  777.     LastView:UpFilter()
  778.     go top
  779.     LastView:Tb:RowPos:=1
  780.     LastView:Tb:Configure()
  781.   endif
  782.   if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif
  783.   return(true)
  784.  
  785.  
  786. //*****************************************************************************
  787. // View:SetReport(nID,WinName,R,C,CurSize,Clr,Shadow) --> true
  788. // select and process selected report
  789. //
  790. method function ViewSetReport(nID,WinName,R,C,CurSize,Clr,Shadow)
  791.   local Ch,Dt,aF
  792.   local TaskID,i
  793.   local Ct:=self  //CurrentTask
  794.   local ar:=Ct:Report[1]
  795.   local object Mnu of Mnu
  796.   local object Report of Report
  797.   if Empty(ar); Alert(ResTxt(080)); return(false); endif
  798.   Mnu:Init("",R,C,CurSize,ar,,Clr,Shadow)
  799.   Ch:=Mnu:Process()
  800.   Mnu:Done()
  801.   if Ch>0
  802.     if( Empty(Ct:=GetLastView(self)), Ct:=self, )
  803.     Dt:=Ct:Report[2,Ch]
  804.     i:=AllTrim(ar[Ch])  //strip number from nemu item for window name for report.
  805.     if Left(i,1)=="~" and IsDigit(SubStr(i,2)) and SubStr(i,3,1)=="."; i:=SubStr(i,4); endif //ƒƒŸ e.g: "~1.The report" --> "The report"
  806.     Report:Init(StrTran(ResTxt(044),"~")+":"+i+": "+WinName)
  807.     aF:=AClone(Dt[2])
  808.     AEval(aF,{|e|ATrueDel(e,1)})
  809.     Report:AddData(Dt[1],aF,Dt[3],Dt[4])  //cTop,aFields,cBottom,lOnlyTotals
  810.     Report:Alias:=Ct:Alias
  811.     Report:IndexNo:=Ct:IndexNo
  812.     if !Ct:FilterMark
  813.       Report:FilterNo:=Ct:FilterNo
  814.       Report:FilterExp:=Ct:FilterExp
  815.     endif
  816.     SetLastTask(nil)  //clear last task, need for repaint; save info for restart task, see c_Task.prg
  817.   endif
  818.   if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif
  819.   return(true)
  820.  
  821.  
  822. //*****************************************************************************
  823. // View:ModIndex(ID,WinName,R,C,CurSize,Clr,Shadow) --> true
  824. // virtual modify index process, last initialization
  825. //
  826. method function ViewModIndex(ID,WinName,R,C,CurSize,Clr,Shadow)
  827.   local arl:={false}
  828.   local ar:={" "+ResTxt(045)+" "}
  829.   local object Mnu of Mnu
  830.   if LogSet()<>1
  831.     Alert(ResTxt(072)+";"+ResTxt(071))
  832.     return(false)
  833.   endif
  834.   default R to Row()
  835.   default C to Col()
  836.   ::MenuNtxID:=ID   //used in EditIndex! (thread task must temporary disable own menu_item!)
  837.   AEval(::OneDbf:Ntx,{|e|AAdd(ar," "+e[1]),AAdd(arl,e[5])})  //cName,lUser
  838.   Mnu:InsBlock:={|Mnu|InsIndex(self,WinName,Clr,Shadow)}
  839.   Mnu:DelBlock:={|Mnu|DelIndex(self,Mnu,R,C,CurSize,ar,arl)}
  840.   Mnu:CanAppend:=true
  841.   if Empty(ar)
  842.     if InsIndex(self,WinName,Clr,Shadow)
  843.       PauseKey(0)  //remove nSwapTask from keyboard queue
  844.     else
  845.       SetLastKey(0)
  846.       return(true)
  847.     endif
  848.   else
  849.     Mnu:Init("",R,C,CurSize,ar,arl)
  850.     if AScan(arl,true)==0; StuffKey(K_INS); endif  //for empty menu do append
  851.     if Mnu:Process()>0; EditIndex(self,Mnu:Choice-1,false,WinName,Clr,Shadow); endif
  852.     Mnu:Done()
  853.   endif
  854.   do case
  855.     case LastKey()==nSwapTask; SetLastKey(K_ENTER)
  856.     case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC)
  857.   endcase
  858.   return(true)
  859.  
  860.  
  861. static function InsIndex(View,WinName,Clr,Shadow)
  862.   local i,cName,cFile
  863.   if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif
  864.   i:=Len(View:OneDbf:Ntx)+1
  865.   cName:="~"+NTrim(i)+"."
  866.   cFile:=cNtxFile+StrTran(Transform(View:ViewID,"99")+Transform(i,"99")," ","0")  //cFile(Name) for new index
  867.   View:OneDbf:AddNtx(cName,cFile,"",false,true)  //cName,cFile,cKey,lUnique,lUser
  868.   EditIndex(View,i,true,WinName,Clr,Shadow)      //append into cIFR
  869.   SetMenuCmd(0)                                  //force restart task (in menu)
  870.   StuffKeys(Chr(nSwapTask)+Chr(K_END))         //exit from Mnu:Process() & restart task, go end of line.
  871.   return(true)
  872.  
  873.  
  874. static function DelIndex(View,Mnu,R,C,CurSize,ar,arl)
  875.   local s:=Select()
  876.   local i:=Mnu:Choice-1
  877.   if AScan(Mnu:SelItems,true)==0; return(false); endif
  878.   if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif
  879.   select (cIFR)
  880.     if FindIfrItem(View,i,"I",false)  //find i-th index item in cIFR
  881.       net delete continue
  882.     endif
  883.   select (s)
  884.   ATrueDel(View:OneDbf:Ntx,i)
  885.   ATrueDel(Mnu:Items,Mnu:Choice)
  886.   ATrueDel(Mnu:SelItems,Mnu:Choice)
  887.   Mnu:Choice:=Min(Mnu:Choice,Len(ar))
  888.   Mnu:Hide()
  889.   Mnu:Init("",R,C,CurSize,ar,arl)
  890.   return(true)
  891.  
  892.  
  893. static function EditIndex(View,i,lAppend,WinName,Clr,Shadow)  //create new task, done menu, go into new task!
  894.   local MaxC:=0
  895.   local cName:=PadR(View:OneDbf:Ntx[i,1],nLenIFRName)
  896.   local cKey:=PadR(View:OneDbf:Ntx[i,3],nLenIFRData-nLenIFRName-20)
  897.   local lUnique:=false
  898.   local object Info of Info   //info-help task
  899.   local object AB of ABrowse  //new task
  900.   local ABName:=if(lAppend,ResTxt(059),ResTxt(041))+" "+Lower(ResTxt(042))
  901.   AEval(View:Fields,{|e|if(!Empty(e[4]) and ValType(e[4])=="C",MaxC:=Max(MaxC,Len(e[3])+Len(e[4])),nil)})
  902.   *
  903.   Info:Buff+=ResTxt(064)+cr_lf+Replicate("-",Len(ResTxt(064)))+cr_lf
  904.   Info:Buff+="Character, Date, Logical, Numeric"+cr_lf+cr_lf
  905.   *
  906.   Info:Buff+=ResTxt(066)+cr_lf+Replicate("-",Len(ResTxt(066)))+cr_lf
  907.   Info:Buff+="Trans(field->XXX,)+Trans(field->YYY,)"+cr_lf+cr_lf
  908.   *
  909.   Info:Buff+=ResTxt(067)+cr_lf+Replicate("-",Len(ResTxt(067)))+cr_lf
  910.   Info:Buff+=View:Alias+cr_lf+cr_lf
  911.   *
  912.   Info:Buff+=ResTxt(068)+cr_lf+Replicate("-",Len(ResTxt(068)))+cr_lf
  913.   AEval(View:Fields,{|e,p|if(!Empty(e[4]) and ValType(e[4])=="C",(p:=Lower(e[3]+"->"+e[4]),Info:Buff+=PadR(Type(p)+":"+p,MaxC+5)),nil)})
  914.   Info:Buff+=cr_lf+cr_lf
  915.   *
  916.   Info:Buff+=ResTxt(069)+cr_lf+Replicate("-",Len(ResTxt(069)))+cr_lf
  917.   Info:Buff+=v_fnc_info+cr_lf+cr_lf
  918.   *
  919.   Info:Buff+=Replicate("-",10)+" "+ResTxt(005)+" "+Replicate("-",10)
  920.   Info:Init(StrTran(ResTxt(057)+" "+Lower(ResTxt(042)),"~")+": "+WinName)
  921.   Info:Row:=2
  922.   Info:RowSize:=MaxRow()-8
  923.   *
  924.   AB:CanSwap:=false
  925.   AB:FormActive:=true
  926.   AB:CanAppend:=false
  927.   AB:MoreRecords:=false
  928.   AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow)
  929.   AB:DoneBlock:={|o|DoneIndex(View,o,i,lAppend,cName,cKey,lUnique,Info)}
  930.   AB:AddBlock(,ResTxt(056),"SYS:->IDX_NAME",{|x|if(nil==x,cName,cName:=x)})
  931.   AB:AddBlock(,ResTxt(061),"SYS:->IDX_KEY", {|x|if(nil==x,cKey,cKey:=x)},,"@S"+NTrim(nLenIFRName+10))
  932.   AB:AddBlock(,ResTxt(063),"SYS:->IDX_UNIQ",{|x|if(nil==x,lUnique,lUnique:=x)},,"@!")
  933.   AB:PostInit()
  934.   AB:Row:=MaxRow()-5
  935.   GetActiveMenu():DisableItem(View:MenuNtxID)  //new task !!!
  936.   SetLastTask(nil)  //must be, because I want do restart this (new) task, not last task.
  937.   return(true)
  938.  
  939.  
  940. static function DoneIndex(View,AB,i,lAppend,cName,cKey,lUnique,Info)  //Save values into: View`OneDbf & cIFR
  941.   local x,s:=""
  942.   local OldS:=Select()
  943.   begin break
  944.     select (View:Alias)
  945.     x:=&(cKey)
  946.   recover break
  947.     select (OldS)
  948.     if Empty(SetLastTask()); AB:Top(false); endif
  949.     if AB:ID<>SetLastTask():ID; AB:Top(false); endif
  950.     if Alert(ResTxt(096)+";"+ResTxt(058)+" "+Lower(ResTxt(061)),ResTxt(124))==1
  951.       AB:Paint(false)
  952.       ATrueDel(View:OneDbf:Ntx,i)
  953.       if !Info:IsDead; Info:Done(); endif
  954.       GetActiveMenu():EnableItem(View:MenuNtxID)
  955.       return(true)
  956.     else
  957.       return(false)
  958.     endif
  959.   end break
  960.   x:=AClone(View:OneDbf:Ntx[i]) //working copy of current index
  961.   x[1]:=AllTrim(cName)
  962.   x[3]:=AllTrim(cKey)
  963.   x[4]:=lUnique
  964.   AEval(x,{|e|s+=v_data_sep+Transform(e,)})
  965.   s:=SubStr(s,Len(v_data_sep)+1)
  966.   select (View:Alias)
  967.   DbClearIndex()
  968.   CreateIndex(x,true)  //x=={cName,cFile,cKey,lUnique}, lContinue
  969.   if NetErr() and lAppend
  970.     ATrueDel(View:OneDbf:Ntx,i)
  971.   else  //index created
  972.     select (cIFR)
  973.     if lAppend
  974.       net append blank continue
  975.     else
  976.       FindIfrItem(View,i,"I",true)
  977.       net rlock continue
  978.     endif
  979.     if NetErr() and lAppend
  980.       ATrueDel(View:OneDbf:Ntx,i)
  981.     else  //record is ready
  982.       field->ViewID:=View:ViewID
  983.       field->Code:="I"
  984.       field->Data:=s
  985.       commit
  986.       net unlock
  987.       View:OneDbf:Ntx[i]:=x  //save info into current Ntx data structure
  988.     endif
  989.   endif
  990.   View:OneDbf:NtxOpen(false)
  991.   if !Info:IsDead; Info:Done(); endif
  992.   GetActiveMenu():EnableItem(View:MenuNtxID)
  993.   select (OldS)
  994.   return(true)
  995.  
  996.  
  997. static function FindIfrItem(View,i,Cd,lCanAppend)    //Cd (Code) can be "I","F","R"
  998.   local n,c
  999.   if Cd=="I"
  1000.     c:=View:OneDbf:Ntx[i,1]    //cName
  1001.   elseif Cd=="F"
  1002.     c:=View:Filter[1,i]        //cName
  1003.   else
  1004.     c:=View:Report[1,i]        //cName
  1005.   endif
  1006.   n:=Len(c)
  1007.   locate for field->ViewID==View:ViewID and field->Code==Cd and Left(field->Data,n)==c
  1008.   if !Found() and lCanAppend
  1009.     net append blank continue
  1010.     if NetErr(); Abort("Can't find this item in database!"); endif
  1011.     field->ViewID:=View:ViewID
  1012.     field->Code:=Cd
  1013.     net unlock
  1014.   endif
  1015.   return(Found())
  1016.  
  1017.  
  1018. //*****************************************************************************
  1019. // View:ModFilter(ID,WinName,R,C,CurSize,Clr,Shadow) --> true
  1020. // virtual modify filter process, last initialization
  1021. //
  1022. method function ViewModFilter(ID,WinName,R,C,CurSize,Clr,Shadow)
  1023.   local Ch
  1024.   local ar:=::Filter[1]
  1025.   local ard:=::Filter[2]
  1026.   local arl:=::Filter[3]
  1027.   local arm:=::Filter[4]
  1028.   local object Mnu of Mnu
  1029.   if LogSet()<>1
  1030.     if Alert(ResTxt(072)+";"+ResTxt(075)+" "+Lower(ResTxt(054))+" "+ResTxt(076),ResTxt(123))<>1
  1031.       return(false)
  1032.     endif
  1033.   endif
  1034.   default R to Row()
  1035.   default C to Col()
  1036.   ::MenuFltID:=ID  //used in EditFilter! (thread task must temporary disable own menu_item!)
  1037.   Mnu:InsBlock:={|Mnu|InsFilter(self,WinName,Clr,Shadow)}
  1038.   Mnu:DelBlock:={|Mnu|DelFilter(self,Mnu,R,C,CurSize,ar,arl)}
  1039.   Mnu:CanAppend:=true
  1040.   if Empty(ar)
  1041.     if InsFilter(self,WinName,Clr,Shadow)
  1042.       PauseKey(0)  //remove nSwapTask from keyboard queue
  1043.     else
  1044.       SetLastKey(0)
  1045.       return(true)
  1046.     endif
  1047.   else
  1048.     Mnu:Init("",R,C,CurSize,ar,arl)
  1049.     if AScan(arl,true)==0; StuffKey(K_INS); endif  //for empty menu do append
  1050.     if Mnu:Process()>0; EditFilter(self,Mnu:Choice,false,WinName,Clr,Shadow); endif
  1051.     Mnu:Done()
  1052.   endif
  1053.   do case
  1054.     case LastKey()==nSwapTask; SetLastKey(K_ENTER)
  1055.     case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC)
  1056.   endcase
  1057.   return(true)
  1058.  
  1059.  
  1060. static function InsFilter(View,WinName,Clr,Shadow)
  1061.   local i,cName,cFile
  1062.   if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif
  1063.   i:=Len(View:Filter[1])+1
  1064.   cName:="~"+NTrim(i-1)+"."
  1065.   AAdd(View:Filter[1],cName)
  1066.   AAdd(View:Filter[2],"")
  1067.   AAdd(View:Filter[3],true)
  1068.   AAdd(View:Filter[4],false)
  1069.   EditFilter(View,i,true,WinName,Clr,Shadow)   //append into cIFR & View`Filter
  1070.   SetMenuCmd(0)                                //force restart task (in menu)
  1071.   StuffKeys(Chr(nSwapTask)+Chr(K_END))         //exit from Mnu:Process() & restart task, go end of line.
  1072.   return(true)
  1073.  
  1074.  
  1075. static function DelFilter(View,Mnu,R,C,CurSize,ar,arl)
  1076.   local x
  1077.   local s:=Select()
  1078.   local i:=Mnu:Choice
  1079.   if AScan(Mnu:SelItems,true)==0; return(false); endif
  1080.   if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif
  1081.   repeat
  1082.     if (x:=LogSet())==1    //delete the filter on disk
  1083.       select (cIFR)
  1084.         if FindIfrItem(View,i,"F",false)
  1085.           net delete continue
  1086.         endif
  1087.       select (s)
  1088.     endif
  1089.   until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1
  1090.   IEval(4,{|j|ATrueDel(View:Filter[j],i)})
  1091.   Mnu:Choice:=Min(Mnu:Choice,Len(ar))
  1092.   Mnu:Hide()
  1093.   Mnu:Init("",R,C,CurSize,ar,arl)
  1094.   return(true)
  1095.  
  1096.  
  1097. static function EditFilter(View,i,lAppend,WinName,Clr,Shadow)  //create new task, done menu, go into new task!
  1098.   local MaxC:=0
  1099.   local cName:=PadR(LTrim(View:Filter[1,i]),nLenIFRName)
  1100.   local cExpr:=PadR(LTrim(View:Filter[2,i]),nLenIFRData-nLenIFRName-20)
  1101.   local lMark:=View:Filter[4,i]
  1102.   local object Info of Info   //info-help task
  1103.   local object AB of ABrowse  //new task
  1104.   local ABName:=if(lAppend,ResTxt(059),ResTxt(041))+" "+Lower(ResTxt(043))
  1105.   AEval(View:Fields,{|e|if(!Empty(e[4]) and ValType(e[4])=="C",MaxC:=Max(MaxC,Len(e[3])+Len(e[4])),nil)})
  1106.   *
  1107.   Info:Buff+=ResTxt(065)+cr_lf+Replicate("-",Len(ResTxt(065)))+cr_lf
  1108.   Info:Buff+="Logical"+cr_lf+cr_lf
  1109.   *
  1110.   Info:Buff+=ResTxt(066)+cr_lf+Replicate("-",Len(ResTxt(066)))+cr_lf
  1111.   Info:Buff+='DtoC(field->XXX)>="31.10.91"'+cr_lf+cr_lf
  1112.   *
  1113.   Info:Buff+=ResTxt(067)+cr_lf+Replicate("-",Len(ResTxt(067)))+cr_lf
  1114.   Info:Buff+=View:Alias+cr_lf+cr_lf
  1115.   *
  1116.   Info:Buff+=ResTxt(068)+cr_lf+Replicate("-",Len(ResTxt(068)))+cr_lf
  1117.   AEval(View:Fields,{|e,p|if(!Empty(e[4]) and ValType(e[4])=="C",(p:=Lower(e[3]+"->"+e[4]),Info:Buff+=PadR(Type(p)+":"+p,MaxC+5)),nil)})
  1118.   Info:Buff+=cr_lf+cr_lf
  1119.   *
  1120.   Info:Buff+=ResTxt(069)+cr_lf+Replicate("-",Len(ResTxt(069)))+cr_lf
  1121.   Info:Buff+=v_fnc_info+cr_lf+cr_lf
  1122.   *
  1123.   Info:Buff+=Replicate("-",10)+" "+ResTxt(005)+" "+Replicate("-",10)
  1124.   Info:Init(StrTran(ResTxt(057)+" "+Lower(ResTxt(043)),"~")+": "+WinName)
  1125.   Info:Row:=2
  1126.   Info:RowSize:=MaxRow()-8
  1127.   *
  1128.   AB:CanSwap:=false
  1129.   AB:FormActive:=true
  1130.   AB:CanAppend:=false
  1131.   AB:MoreRecords:=false
  1132.   AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow)
  1133.   AB:DoneBlock:={|o|DoneFilter(View,o,i,lAppend,cName,cExpr,lMark,Info)}
  1134.   AB:AddBlock(,ResTxt(056),"SYS:->FLT_NAME",{|x|if(nil==x,cName,cName:=x)})
  1135.   AB:AddBlock(,ResTxt(062),"SYS:->FLT_EXPR",{|x|if(nil==x,cExpr,cExpr:=x)},,"@S"+NTrim(nLenIFRName+10))
  1136.   AB:AddBlock(,ResTxt(181),"SYS:->FLT_PROP",{|x|if(!Empty(x),lMark:=!lMark,)," "+if(lMark,ResTxt(182),ResTxt(183))+" "},{|AB|DoGetMark(AB)})
  1137.   AB:PostInit()
  1138.   AB:Row:=MaxRow()-5
  1139.   GetActiveMenu():DisableItem(View:MenuFltID)  //new task !!!
  1140.   SetLastTask(nil)  //must be, because I want do restart this (new) task, not last task.
  1141.   return(true)
  1142.  
  1143. static function DoGetMark(AB)
  1144.   local Get:=AB:GetList[AB:Tb:ColPos]
  1145.   Get:Row:=AB:Row+AB:Freeze-AB:FormTop+AB:Tb:ColPos+1
  1146.   Get:Col:=AB:Col+Get:Cargo[nColOffset]
  1147.   EditGet(Get,false)
  1148.   if LastKey()==K_ENTER; Get:VarPut("x"); endif
  1149.   return(true)
  1150.  
  1151.  
  1152. static function DoneFilter(View,AB,i,lAppend,cName,cExpr,lMark,Info)  //Save values into: View:Filter & cIFR
  1153.   local x
  1154.   local OldS:=Select()
  1155.   cName:=" "+AllTrim(cName)+" "
  1156.   cExpr:=AllTrim(cExpr)
  1157.   begin break
  1158.     select (View:Alias)
  1159.     x:=&(cExpr)
  1160.   recover break
  1161.     select (OldS)
  1162.     if Empty(SetLastTask()); AB:Top(false); endif
  1163.     if AB:ID<>SetLastTask():ID; AB:Top(false); endif
  1164.     if Alert(ResTxt(096)+";"+ResTxt(058)+" "+Lower(ResTxt(062)),ResTxt(124))==1
  1165.       AB:Paint(false)
  1166.       IEval(4,{|j|ATrueDel(View:Filter[j],i)})
  1167.       if !Info:IsDead; Info:Done(); endif
  1168.       GetActiveMenu():EnableItem(View:MenuFltID)
  1169.       return(true)
  1170.     else
  1171.       return(false)
  1172.     endif
  1173.   end break
  1174.   View:Filter[1,i]:=cName
  1175.   View:Filter[2,i]:=cExpr
  1176.   View:Filter[4,i]:=lMark
  1177.   repeat
  1178.     if (x:=LogSet())==1    //save the filter on disk
  1179.       select (cIFR)
  1180.       if lAppend
  1181.         net append blank continue
  1182.       else
  1183.         FindIfrItem(View,i,"F",true)
  1184.         net rlock continue
  1185.       endif
  1186.       if NetErr(); select (OldS); return(false); endif
  1187.       field->ViewID:=View:ViewID
  1188.       field->Code:="F"
  1189.       field->Data:=cName+v_data_sep+cExpr+v_data_sep+Transform(lMark,)
  1190.       commit
  1191.       net unlock
  1192.     endif
  1193.   until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1
  1194.   if !Info:IsDead; Info:Done(); endif
  1195.   GetActiveMenu():EnableItem(View:MenuFltID)
  1196.   select (OldS)
  1197.   return(true)
  1198.  
  1199.  
  1200. //*****************************************************************************
  1201. // View:ModReport(ID,WinName,R,C,CurSize,Clr,Shadow) --> nil
  1202. // virtual modify Report process
  1203. //
  1204. method function ViewModReport(ID,WinName,R,C,CurSize,Clr,Shadow)
  1205.   local Ch
  1206.   local ar:=::Report[1]
  1207.   local arl:=::Report[3]
  1208.   local object Mnu of Mnu
  1209.   if LogSet()<>1
  1210.     if Alert(ResTxt(072)+";"+ResTxt(075)+" "+Lower(ResTxt(055))+" "+ResTxt(076),ResTxt(123))<>1
  1211.       return(false)
  1212.     endif
  1213.   endif
  1214.   default R to Row()
  1215.   default C to Col()
  1216.   ::MenuRptID:=ID  //used in EditReport! (thread task must temporary disable own menu_item!)
  1217.   Mnu:InsBlock:={|Mnu|InsReport(self,WinName,Clr,Shadow)}
  1218.   Mnu:DelBlock:={|Mnu|DelReport(self,Mnu,R,C,CurSize,ar,arl)}
  1219.   Mnu:CanAppend:=true
  1220.   if Empty(ar)
  1221.     if InsReport(self,WinName,Clr,Shadow)
  1222.       PauseKey(0)  //remove nSwapTask from keyboard queue
  1223.     else
  1224.       SetLastKey(0)
  1225.       return(true)
  1226.     endif
  1227.   else
  1228.     Mnu:Init("",R,C,CurSize,ar,arl)
  1229.     if AScan(arl,true)==0; StuffKey(K_INS); endif  //for empty menu do append
  1230.     if Mnu:Process()>0; EditReport(self,Mnu:Choice,false,WinName,Clr,Shadow); endif
  1231.     Mnu:Done()
  1232.   endif
  1233.   do case
  1234.     case LastKey()==nSwapTask; SetLastKey(K_ENTER)
  1235.     case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC)
  1236.   endcase
  1237.   return(true)
  1238.  
  1239.  
  1240. static function InsReport(View,WinName,Clr,Shadow)
  1241.   local i,cName,cFile
  1242.   if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif
  1243.   i:=Len(View:Report[1])+1
  1244.   cName:="~"+NTrim(i)+"."
  1245.   AAdd(View:Report[1],cName)
  1246.   AAdd(View:Report[2],{"",{},"",false})        //in future := {cTop,aFields,cBottom,lOnlyTotals}
  1247.   AAdd(View:Report[3],true)
  1248.   EditReport(View,i,true,WinName,Clr,Shadow)   //append into cIFR & View:Report
  1249.   SetMenuCmd(0)                                //force restart task (in menu)
  1250.   StuffKeys(Chr(nSwapTask)+Chr(K_END))         //exit from Mnu:Process() & restart task, go end of line.
  1251.   return(true)
  1252.  
  1253.  
  1254. static function DelReport(View,Mnu,R,C,CurSize,ar,arl)
  1255.   local x
  1256.   local s:=Select()
  1257.   local i:=Mnu:Choice
  1258.   if AScan(Mnu:SelItems,true)==0; return(false); endif
  1259.   if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif
  1260.   repeat
  1261.     if (x:=LogSet())==1    //delete the report on disk
  1262.       select (cIFR)
  1263.         if FindIfrItem(View,i,"R",false)
  1264.           net delete continue
  1265.         endif
  1266.       select (s)
  1267.     endif
  1268.   until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1
  1269.   IEval(3,{|j|ATrueDel(View:Report[j],i)})
  1270.   Mnu:Choice:=Min(Mnu:Choice,Len(ar))
  1271.   Mnu:Hide()
  1272.   Mnu:Init("",R,C,CurSize,ar,arl)
  1273.   return(true)
  1274.  
  1275.  
  1276. static function EditReport(View,i,lAppend,WinName,Clr,Shadow)    //create new task, done menu, go into new task!
  1277.   local cName:=PadR(LTrim(View:Report[1,i]),nLenIFRName)
  1278.   local cTop:=PadR(LTrim(View:Report[2,i,1]),n_foot_max)
  1279.   local aFields:=View:Report[2,i,2]
  1280.   local cBottom:=PadR(LTrim(View:Report[2,i,3]),n_foot_max)
  1281.   local lOnlyTotals:=View:Report[2,i,4]
  1282.   local object AB of ABrowse  //new task
  1283.   local ABName:=if(lAppend,ResTxt(060),ResTxt(041))+" "+Lower(ResTxt(044))
  1284.   AB:CanSwap:=false
  1285.   AB:FormActive:=true
  1286.   AB:CanAppend:=false
  1287.   AB:MoreRecords:=false
  1288.   AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow)
  1289.   AB:AddBlock(,ResTxt(056),"SYS:->RPT_NAME",  {|x|if(nil==x,cName,cName:=x)})
  1290.   AB:AddBlock(,ResTxt(047),"SYS:->RPT_TOP",   {|x|if(nil==x,cTop,cTop:=x)},,"@S"+NTrim(nLenTopBottom))
  1291.   AB:AddBlock(,ResTxt(048),"SYS:->RPT_FIELDS",{||ResTxt(133)},,,,{||if(LastKey()==K_ENTER,FieldProcess(View,i,Clr,Shadow),true)})
  1292.   AB:AddBlock(,ResTxt(049),"SYS:->RPT_BOTTOM",{|x|if(nil==x,cBottom,cBottom:=x)},,"@S"+NTrim(nLenTopBottom))
  1293.   AB:AddBlock(,ResTxt(193),"SYS:->RPT_ONLY",  {|x|if(!Empty(x),lOnlyTotals:=!lOnlyTotals,)," "+ResTxt(123)[if(lOnlyTotals,1,2)]+" "},{|AB|DoGetMark(AB)})
  1294.   AB:PostInit()
  1295.   AB:DoneBlock:={|o|DoneReport(View,o,i,lAppend,cName,cTop,cBottom,lOnlyTotals)}
  1296.   GetActiveMenu():DisableItem(View:MenuRptID)  //new task !!!
  1297.   SetLastTask(nil)  //must be, because I want do restart this new task, not last task.
  1298.   return(true)
  1299.  
  1300.  
  1301. static function FieldProcess(View,ii,Clr,Shadow)
  1302.   local i,ee,p,p1,p2,p3,p4,p5,p6
  1303.   local cYes:=ResTxt(123)[1]
  1304.   local cNo:=Space(Len(cYes))
  1305.   local MaxC:=0
  1306.   local MnuItems:={}
  1307.   local object UpAb of UpABrowse
  1308.   local OldShow:=SetDialog(true)
  1309.   local OldHelp:=SetHelpIdx(true)
  1310.   local aFields:=View:Report[2,ii,2]
  1311.   SetCursor(SC_NONE)
  1312.   SaveDOut(ResTxt(162))
  1313.   AEval(View:Fields,{|e|MaxC:=Max(MaxC,Len(e[2]))})
  1314.   AEval(View:Fields,{|e|AAdd(MnuItems," "+PadR(e[2],MaxC+1))})
  1315.   //
  1316.   //always add recNo()
  1317.   ee:=if(Empty(aFields),false,(aFields[1,1]==ResTxt(051)))
  1318.   AAdd(UpAb:Arr,{ee, PadR(ResTxt(051),MaxC), if(ee,aFields[1,2],PadR(ResTxt(051),nLenColTitle)), false, 0})
  1319.   //
  1320.   //Get all fields from View:Fields, set "˚" for field from aFields
  1321.   //UpAb:Arr:={{lSelected,cShortName,cTitle,lTotal,nIndexSubTotal},...}
  1322.   //View:Report[2,i,2]:=aFields:={{cShortName,cTitle,cField,cPicture,lTotal,cSubTotal},...}
  1323.   //View:Fields:={{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid},...}
  1324.   for i:=1 to Len(View:Fields)
  1325.     ee:=View:Fields[i]
  1326.     p1:=(p:=AScan(aFields,{|x|x[3]==if(ValType(ee[4])=="B",ee[3],ee[3]+"->"+ee[4])},,i+1))>0
  1327.     p2:=PadR(ee[2],MaxC)
  1328.     p3:=PadR(if(p1,aFields[p,2],p2),nLenColTitle)
  1329.     p4:=p1 and !Empty(aFields[p,5])
  1330.     p5:=if(p1 and !Empty(aFields[p,6]),;
  1331.            AScan(View:Fields,{|x|aFields[p,6]==if(ValType(x[4])=="B",x[3],x[3]+"->"+x[4])}),;
  1332.            0;
  1333.           )
  1334.     AAdd(UpAb:Arr,{p1,p2,p3,p4,p5})
  1335.   endfor
  1336.   UpAb:GoodInit(ResTxt(082),-3,-3,Min(Len(UpAb:Arr)+2,MaxRow()-5),Min(4+Max(Len(ResTxt(083)),MaxC)+3+Max(Len(ResTxt(194)),nLenColTitle)+3+Max(Len(ResTxt(084)),Len(cYes))+3+Max(Len(ResTxt(085)),MaxC)+1,MaxCol()-6))
  1337.   UpAb:AddBlock(,Chr(240),,{||if(UpAb:Arr[UpAb:N,1],"˚","x")} )
  1338.   UpAb:AddBlock(,ResTxt(083),"SYS:->RPT_IN_SEL",  {||UpAb:Arr[UpAb:N,2]}, {||DoGetField(UpAb,View)} )
  1339.   UpAb:AddBlock(,ResTxt(194),"SYS:->RPT_IN_TITLE",{|x|if(nil==x,UpAb:Arr[UpAb:N,3],UpAb:Arr[UpAb:N,3]:=x)}, {||DoGetTitle(UpAb,View)} )
  1340.   UpAb:AddBlock(,ResTxt(084),"SYS:->RPT_IN_TOT",  {||if(UpAb:Arr[UpAb:N,4],cYes,cNo)}, {||DoGetTotal(UpAb,View)} )
  1341.   UpAb:AddBlock(,ResTxt(085),"SYS:->RPT_IN_SUBT", {||if(UpAb:Arr[UpAb:N,5]>0,UpAb:Arr[UpAb:Arr[UpAb:N,5],2],Space(MaxC))}, {||DoGetSubTotal(UpAb,View,MnuItems,Clr,Shadow)} )
  1342.   for p:=1 to 5
  1343.     (UpAb:Tb:GetColumn(p)):ColorBlock:={||if(UpAb:Arr[UpAb:N,1],{nNormal,nUnSelect},{nExtension,nUnSelect})}
  1344.   endfor
  1345.   UpAb:CanMoveCursor:=false
  1346.   UpAb:CanAppend:=false
  1347.   UpAb:CanSwap:=false
  1348.   UpAb:Freeze:=1
  1349.   UpAb:Paint()
  1350.   DOut(ResTxt(154)); SetDialog(false)
  1351.   SaveHelpIdx({14}); SetHelpIdx(false)
  1352.   UpAb:Process()  //---------------------------------------------
  1353.   SetHelpIdx(true); RestHelpIdx(); SetHelpIdx(OldHelp)
  1354.   SetDialog(true); RestDOut(); SetDialog(OldShow)
  1355.   View:Report[2,ii,2]:={}
  1356.   //
  1357.   //work around RecNo()
  1358.   if UpAb:Arr[1,1]; AAdd(View:Report[2,ii,2],{ResTxt(051),UpAb:Arr[1,3],"RecNo()",,,}); endif
  1359.   //
  1360.   //build View:Report[2,ii,2]
  1361.   //UpAb:Arr:={{lSelected,cShortName,cTitle,lTotal,nIndexSubTotal},...}    (paralel array for View:Fields)
  1362.   //View:Report[2,ii,2]:=aFields:={{cShortName,cTitle,cField,cPicture,lTotal,cSubTotal},...}
  1363.   //View:Fields:={{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid},...}
  1364.   for i:=2 to Len(UpAb:Arr)
  1365.     ee:=UpAb:Arr[i]
  1366.     if ee[1]
  1367.       p1:=View:Fields[i-1,2]
  1368.       p2:=AllTrim(ee[3])
  1369.       p3:=View:Fields[i-1,3]+"->"+View:Fields[i-1,4]
  1370.       p4:=if(!Empty(View:Fields[i-1,5]), View:Fields[i-1,5], nil)
  1371.       p5:=if(ee[4], true, nil)
  1372.       p6:=if(ee[5]>1, View:Fields[ee[5]-1,3]+"->"+View:Fields[ee[5]-1,4], nil)
  1373.       AAdd(View:Report[2,ii,2],{p1,p2,p3,p4,p5,p6})
  1374.     endif
  1375.   endfor
  1376.   UpAb:Done()
  1377.   RestDOut()
  1378.   SetLastKey(0)
  1379.   StuffKey(K_DOWN)
  1380.   return(true)   //into validation of EditReport
  1381.  
  1382.  
  1383. static function DoGetField(UpAb,View)
  1384.   returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false
  1385.   UpAb:Arr[UpAb:N,1]:=!UpAb:Arr[UpAb:N,1]
  1386.   if !UpAb:Arr[UpAb:N,1]
  1387.     UpAb:Arr[UpAb:N,4]:=false
  1388.     UpAb:Arr[UpAb:N,5]:=0
  1389.   endif
  1390.   UpAb:Tb:RefreshCurrent()
  1391.   PauseKey()
  1392.   StuffKey(K_DOWN)
  1393.   return(true)
  1394.  
  1395.  
  1396. static function DoGetTitle(UpAb,View)
  1397.   returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false
  1398.   UpAb:Arr[UpAb:N,1]:=true
  1399.   UpAb:DoGet()
  1400.   UpAb:Tb:RefreshCurrent()
  1401.   StuffKey(K_DOWN)
  1402.   return(true)
  1403.  
  1404.  
  1405. static function DoGetTotal(UpAb,View)
  1406.   returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false
  1407.   if UpAb:N>1
  1408.     UpAb:Arr[UpAb:N,4]:=!UpAb:Arr[UpAb:N,4]
  1409.     if ValType(&(View:Fields[UpAb:N-1,3]+"->"+View:Fields[UpAb:N-1,4]))<>"N"
  1410.       Alert(ResTxt(077))
  1411.       UpAb:Arr[UpAb:N,4]:=false
  1412.     endif
  1413.     if UpAb:Arr[UpAb:N,4]
  1414.       UpAb:Arr[UpAb:N,1]:=true
  1415.     else
  1416.       UpAb:Arr[UpAb:N,5]:=0
  1417.     endif
  1418.     UpAb:Tb:RefreshCurrent()
  1419.   endif
  1420.   PauseKey()
  1421.   StuffKey(K_DOWN)
  1422.   return(true)
  1423.  
  1424.  
  1425. static function DoGetSubTotal(UpAb,View,MnuItems,Clr,Shadow)
  1426.   local lExit,Choice
  1427.   returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false
  1428.   if UpAb:N>1
  1429.     lExit:=false
  1430.     object Choice of Choice
  1431.     if UpAb:Arr[UpAb:N,5]>0
  1432.       UpAb:Arr[UpAb:N,5]:=0
  1433.     else
  1434.       if ValType(&(View:Fields[UpAb:N-1,3]+"->"+View:Fields[UpAb:N-1,4]))<>"N"
  1435.         Alert(ResTxt(077))
  1436.         UpAb:Arr[UpAb:N,4]:=false
  1437.       else
  1438.         Choice:FastInit(,Row(),Col(),UpAb:Tb:ColWidth(4),MnuItems,Clr,Shadow)
  1439.         UpAb:Arr[UpAb:N,5]:=Choice:Process()
  1440.         Choice:Done()
  1441.         if UpAb:Arr[UpAb:N,5]>0
  1442.           UpAb:Arr[UpAb:N,1]:=true
  1443.           UpAb:Arr[UpAb:N,4]:=true
  1444.           UpAb:Arr[UpAb:N,5]++
  1445.         endif
  1446.       endif
  1447.     endif
  1448.     UpAb:Tb:RefreshCurrent()
  1449.   endif
  1450.   PauseKey()
  1451.   StuffKey(K_DOWN)
  1452.   return(true)
  1453.  
  1454.  
  1455. static function DoneReport(View,AB,i,lAppend,cName,cTop,cBottom,lOnlyTotals)  //Save values into: View:Report & cIFR
  1456.   local x
  1457.   local cExpr:=""
  1458.   local OldS:=Select()
  1459.   local aFields:=View:Report[2,i,2]
  1460.   if Empty(aFields)
  1461.     select (OldS)
  1462.     if Empty(SetLastTask()); AB:Top(false); endif
  1463.     if AB:ID<>SetLastTask():ID; AB:Top(false); endif
  1464.     if Alert(ResTxt(095),ResTxt(124))==1
  1465.       AB:Paint(false)
  1466.       IEval(3,{|j|ATrueDel(View:Report[j],i)})
  1467.       GetActiveMenu():EnableItem(View:MenuRptID)
  1468.       return(true)
  1469.     else
  1470.       return(false)
  1471.     endif
  1472.   endif
  1473.   AEval(aFields,{|e|cExpr+=";"+e[1]+","+;
  1474.                                e[2]+","+;
  1475.                                e[3]+","+;
  1476.                                if(nil==e[4],"",e[4])+","+;
  1477.                                if(nil==e[5],"F",Transform(e[5],))+","+;
  1478.                                if(nil==e[6],"",e[6]);
  1479.                 };                  //cShortName,cTitle,cField,cPicture,lTotal,cSubTotal
  1480.        )
  1481.   cName:=" "+AllTrim(cName)+" "
  1482.   cTop:=AllTrim(cTop)
  1483.   cBottom:=AllTrim(cBottom)
  1484.   View:Report[1,i]:=cName
  1485.   View:Report[2,i,1]:=cTop
  1486.   View:Report[2,i,3]:=cBottom
  1487.   View:Report[2,i,4]:=lOnlyTotals
  1488.   View:Report[3,i]:=true
  1489.   repeat
  1490.     if (x:=LogSet())==1    //save the filter on disk
  1491.       select (cIFR)
  1492.       if lAppend
  1493.         net append blank continue
  1494.       else
  1495.         FindIfrItem(View,i,"R",true)
  1496.         net rlock continue
  1497.       endif
  1498.       if NetErr(); select (OldS); return(false); endif
  1499.       field->ViewID:=View:ViewID
  1500.       field->Code:="R"
  1501.       field->Data:=cName+v_data_sep+cTop+v_data_sep+SubStr(cExpr,2)+v_data_sep+cBottom+v_data_sep+Transform(lOnlyTotals,)
  1502.       commit
  1503.       net unlock
  1504.     endif
  1505.   until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1
  1506.   GetActiveMenu():EnableItem(View:MenuRptID)
  1507.   select (OldS)
  1508.   return(true)
  1509.  
  1510.  
  1511. //*****************************************************************************
  1512. // View:VProcess() --> true
  1513. // thread virtual view or edit process
  1514. // called how Task:VProcess()
  1515. //
  1516. method function ViewVProcess()
  1517.   local cMsg:=""
  1518.   local OldKey:=SetKey(K_ALT_F10,{||SlipMenu(self)})
  1519.   AEval(::Action,{|e|e[3]:=SetKey(e[1],e[2]),if(!Empty(e[4]) and ValType(e[4])=="C",cMsg+=","+e[4],nil)})
  1520.   cMsg:=StrTran(cMsg,",,",",")
  1521.   ::AddMsg:=SubStr(cMsg,2)
  1522.   ::super(DBrowse):VProcess()
  1523.   AEval(::Action,{|e|SetKey(e[1],e[3])})
  1524.   SetKey(K_ALT_F10,OldKey)
  1525.   return(true)
  1526.  
  1527.  
  1528. //-----------------------------------------------------------------------------
  1529. // View::SlipMenu() --> true/false
  1530. // slip menu for thread virtual view or edit process
  1531. //
  1532. static function SlipMenu(View)
  1533.   local Action,Menu,MD
  1534.   if Empty(View:MenuID); return(false); endif
  1535.   Menu:=GetActiveMenu()
  1536.   MD:=Menu:GetParentMD(View:MenuID)
  1537.   SetCursor(SC_NONE)
  1538.   SetPos(View:Row,View:Col+2)
  1539.   SaveDOut(ResTxt(140)+if(!Empty(View:AddMsg),","+View:AddMsg,""))
  1540.   SaveHelpIdx({}) //disable menu
  1541.   if (Action:=Menu:ItemEntry(MD,-1))>0 and !Empty(Menu:Block[Action])
  1542.     Menu:NewTask:=Action
  1543.     StuffKey(nSwapTask)
  1544.   else
  1545.     if Action>0
  1546.       SetMenuCmd(0)
  1547.       StuffKey(nSwapTask)
  1548.     else
  1549.       if SetQuickEsc(); InKeyWait(); endif //remove Esc from queue
  1550.     endif
  1551.   endif
  1552.   RestHelpIdx()
  1553.   RestDOut()
  1554.   return(true)
  1555.  
  1556.  
  1557. //*****************************************************************************
  1558. // View:Done(lRePaint) --> true/false
  1559. // destroy this object.
  1560. //
  1561. method function ViewDone(lRePaint)
  1562.   local lExit:=::super(DBrowse):Done(lRePaint)
  1563.   if lExit
  1564.     ATrueDel(VList,AScan(VList,{|e|e:ID==::ID}))   //this is Window:ID (unique for each window, i.e: unique for each live view object)
  1565.   endif
  1566.   return(lExit)
  1567.  
  1568. //------------------------------------------------------- eof (c)JHK ----------
  1569.  
  1570.